package com.tuozixuan.handler;

import static com.tuozixuan.constant.GitConstants.PASSWORD;
import static com.tuozixuan.constant.GitConstants.USERNAME;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tuozixuan.base.Branch;
import com.tuozixuan.base.Version;
import com.tuozixuan.config.Config;
import com.tuozixuan.constant.OperateEnum;
import com.tuozixuan.util.GitUtils;
import com.tuozixuan.util.MvnUtils;
import com.tuozixuan.util.ProjectUtils;

public class NewBranchHandler implements Handler {
	
	private static Logger logger = LoggerFactory.getLogger(NewBranchHandler.class);

	@Override
	public void execute(Config config) throws Exception {
		
		String mavenHome = System.getenv("MAVEN_HOME");
		if (StringUtils.isBlank(mavenHome)) {
			logger.error("MAVEN_HOME环境变量未设置！");
			return;
		}
		logger.info("MAVEN_HOME:{}", mavenHome);
		
		String mvnCmd = StringUtils.appendIfMissing(mavenHome, File.separator) + "bin" + File.separator + "mvn.cmd";
		logger.info("mvnCmd:{}", mvnCmd);
		
		CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(USERNAME, PASSWORD);
		Map<String, String> projectMap = config.getProjects();
		for (Map.Entry<String, String> entry : projectMap.entrySet()) {	
			String projectName = entry.getKey();
			String targetBranch = entry.getValue();
			
			String projectPath = config.getBasePath() + File.separator + projectName;
			logger.info("{} projectPath:{}", projectName, projectPath);
			
			File projectWorkPath = new File(projectPath);
			Git git = Git.open(projectWorkPath);
			Status status = git.status().call();
			if (!status.isClean()) {
				logger.error("{} 存在未提交的文件。status:{}", projectName, status);
				return;
			}
			
			PullResult pullResult = git.pull().setCredentialsProvider(credentialsProvider).call();
			logger.info("{} pullResult:{}", projectName, pullResult);
			if (!pullResult.isSuccessful()) {
				logger.error("{} pull失败", projectName);
				return;
			}
			
			String currentBranchName = git.getRepository().getBranch();
			logger.info("{} currentBranchName:{}", projectName, currentBranchName);
			if (!StringUtils.equals(currentBranchName, targetBranch)) {
				logger.info("当前分支({})与目标分支({})不一致，即将切换到目标分支", currentBranchName, targetBranch);
				git.checkout().setName(targetBranch).call();
				currentBranchName = git.getRepository().getBranch();
				logger.info("已经切换到{}分支", currentBranchName);
			}
			
			List<String> modifyPomFileList = ProjectUtils.getRelativePathNameListByFileName(projectPath, "pom.xml", "/");
			logger.info("{} modifyPomFileList:{}", projectName, modifyPomFileList);
			
			Branch currentBranch = Branch.of(currentBranchName);
			String newBranchName = currentBranch.minorIncrement().toString();
			logger.info("{} newBranchName:{}", projectName, newBranchName);
			
			boolean existLocalBranch = GitUtils.existLocalBranch(git, newBranchName);
			if (existLocalBranch) {
				logger.error("{} 已经存在本地分支：{}", projectName, newBranchName);
				return;
			}
			boolean existRemoteBranch = GitUtils.existRemoteBranch(git, newBranchName);
			if (existRemoteBranch) {
				logger.error("{} 已经存在远程分支：{}", projectName, newBranchName);
				return;
			}
			
			git.branchCreate().setName(newBranchName).call();
			git.checkout().setName(newBranchName).call();
			logger.info("{} 创建并切换到本地分支：{}", projectName, newBranchName);
			
			changeNewBrachVersion(mvnCmd, projectWorkPath);
			logger.info("{} 改变版本号完成", projectName);
			
			GitUtils.addFilepatternList(git, modifyPomFileList);
			
			String message = "[Auto]new Branch " + newBranchName;
			GitUtils.commitAndPush(git, message, credentialsProvider);
			logger.info("{} push新的分支完成", projectName);
			logger.info("{} end", projectName);
			
		}
	}
	
	private static void changeNewBrachVersion(String mvnCmd, File projectWorkPath) {
		
		String localVersion = MvnUtils.getVersion(mvnCmd, projectWorkPath);
		logger.info("localVersion:{}", localVersion);
		
		Version version = Version.of(localVersion);
		Version newVersion = version.minorIncrement().revisionReset();
		logger.info("newVersion:{}", newVersion);
		
		MvnUtils.changeVersion(mvnCmd, projectWorkPath, newVersion);
		MvnUtils.changeDependencyVersion(mvnCmd, projectWorkPath, newVersion);
	}

	@Override
	public OperateEnum getOperate() {
		return OperateEnum.NEW_BRANCH;
	}

}
